package cmpe451.group7.ourcity.dao.impl;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cmpe451.group7.ourcity.dao.GenericDAO;
import cmpe451.group7.ourcity.util.Logger;

@Repository("genericDAO")
public abstract class GenericDAOImpl<T extends Serializable> implements
		GenericDAO<T>, Serializable {

	private static final long serialVersionUID = -3851117910767424885L;

	@Autowired
	protected SessionFactory sessionFactory;

	protected Session getCurrentSession() {
		return sessionFactory.getCurrentSession();
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public boolean save(T entity) {
		try {
			Session session = this.getCurrentSession();
			session.save(entity);
			//session.flush();

			return true;
		} catch (HibernateException e) {
			Logger.log(e);
		}
		return false;
	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean saveOrUpdate(T entity) {
		Session session = this.getCurrentSession();
		session.saveOrUpdate(entity);
		//session.flush();

		return true;
	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean merge(T entity) {
		Session session = this.getCurrentSession();
		session.merge(entity);
		//session.flush();

		return true;
	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean update(T entity) {
		Session session = this.getCurrentSession();
		session.update(entity);
		//session.flush();

		return true;
	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean delete(T entity) {
		Session session = this.getCurrentSession();
		session.delete(entity);
		//session.flush();

		return true;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	protected T findByID(Class sinif, long id) {
		Session session = this.getCurrentSession();
		T entity = (T) session.get(sinif, id);
		return entity;
	}

	@SuppressWarnings("unchecked")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	protected List<T> findAll(Class<T> sinif) {
		Session session = this.getCurrentSession();
		Criteria criteria = session.createCriteria(sinif.getName());
		List<T> resultSet = criteria.setResultTransformer(
				Criteria.DISTINCT_ROOT_ENTITY).list();
		return resultSet;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void initialize(Object entity) {
		Hibernate.initialize(entity);
	}
}
